package com.example.demo.service.impl;

import com.example.demo.constant.RedisKey;
import com.example.demo.enumeration.Campus;
import com.example.demo.mapper.*;
import com.example.demo.pojo.entity.Item;
import com.example.demo.pojo.entity.User;
import com.example.demo.pojo.properties.AliyunOssProperties;
import com.example.demo.pojo.vo.ItemListVO;
import com.example.demo.pojo.vo.PageVO;
import com.example.demo.pojo.vo.UserDetailVO;
import com.example.demo.pojo.vo.UserProfileVO;
import com.example.demo.service.UserService;
import com.example.demo.utils.AliyunOssUtil;
import com.example.demo.utils.JwtUtil;
import com.example.demo.utils.ThreadLocalUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private FavouriteMapper favouriteMapper;
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private ItemImageMapper itemImageMapper;
    @Autowired
    private FollowMapper followMapper;
    @Autowired
    private CampusMapper campusMapper;
    @Autowired
    private ViewHistoryMapper viewHistoryMapper;
    @Autowired
    private AliyunOssProperties aliyunOssProperties;
    @Autowired
    private StringRedisTemplate stringRedisTemplate; //报错信息错误，无影响

    @Override
    public boolean checkPhoneExists(String phone) {
        return userMapper.selectByPhone(phone) != null;
    }

    @Override
    public boolean checkNameExists(String name) {
        return userMapper.selectByName(name) != null;
    }

    @Override
    public boolean validateVerificationCode(String phone, String code) {
        String verificationCode = stringRedisTemplate.opsForValue().get(phone);;

        return code.equals(verificationCode);
    }

    @Override
    public void deleteVerificationCode(String phone) {
        stringRedisTemplate.opsForValue().getOperations().delete(phone);
    }

    @Override
    public void deleteToken(Long id) {
        stringRedisTemplate.opsForValue().getOperations().delete(RedisKey.USER_PREFIX + id);
    }

    @Override
    public User selectById(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public String selectNameById(Long id) {
        return userMapper.selectNameById(id);
    }

    @Override
    public User selectByPhone(String phone) {
        return userMapper.selectByPhone(phone);
    }

    @Override
    public User selectByName(String name) {
        return userMapper.selectByName(name);
    }

    @Override
    public boolean register(String phone, String name, String password, String studentId, Campus campus) {
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        String defaultPicture = aliyunOssProperties.getDefaultPicture();

        return userMapper.createUser(phone, name, password, studentId, campus, defaultPicture);
    }

    @Override
    public boolean checkPassword(String phone, String password) {
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        String pwd = userMapper.selectByPhone(phone).getPassword();

        return password.equals(pwd);
    }

    @Override
    public String generateUserToken(Long id) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", id);

        String token = JwtUtil.getToken(claims);

        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(RedisKey.USER_PREFIX + id, token, 7, TimeUnit.DAYS);

        return token;
    }

    @Override
    public Long getCurrentUserId() {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long id = Long.parseLong(map.get("id").toString());

        return id;
    }

    @Override
    public User getCurrentUser() {
        Long currentUserId = getCurrentUserId();

        return userMapper.selectById(currentUserId);
    }

    @Override
    public UserProfileVO getCurrentUserProfile() {
        Long currentUserId = getCurrentUserId();
        return userMapper.getUserProfile(currentUserId);
    }

    @Override
    public UserProfileVO getUserProfile(Long id) {
        return userMapper.getUserProfile(id);
    }

    @Override
    public UserDetailVO getUserDetail(Long id) {
        return userMapper.getUserDetail(id);
    }

    @Override
    public boolean updateInfo(String name, Campus campus) {
        Long currentUserId = getCurrentUserId();

        return userMapper.updateInfo(name, campus, currentUserId);
    }

    @Override
    public boolean updatePicture(String url) {
        User currentUser = getCurrentUser();
        Long id = currentUser.getId();
        String picture = currentUser.getPicture();

        String objectName = picture.substring(picture.lastIndexOf("/") + 1);

        if (!picture.equals(aliyunOssProperties.getDefaultPicture())) {
            AliyunOssUtil.deleteFile(aliyunOssProperties, objectName);
        }

        return userMapper.updatePicture(url, id);
    }

    @Override
    public boolean updatePassword(String password, Long id) {
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        return userMapper.updatePassword(password, id);
    }

    @Override
    public Long selectFavouriteIdByIds(Long itemId) {
        Long currentUserId = getCurrentUserId();

        return favouriteMapper.selectIdByIds(currentUserId, itemId);
    }

    @Override
    public boolean addFavourite(Long itemId) {
        Long currentUserId = getCurrentUserId();

        return favouriteMapper.addFavourite(currentUserId, itemId);
    }

    @Override
    public boolean deleteFavourite(Long itemId) {
        Long currentUserId = getCurrentUserId();

        return favouriteMapper.deleteFavourite(currentUserId, itemId);
    }

    @Override
    public List<ItemListVO> getFavouriteList() {
        Long currentUserId = getCurrentUserId();
        List<Long> itemIds = favouriteMapper.selectItemIdByUserId(currentUserId);

        List<ItemListVO> list = new ArrayList<>();

        for (Long itemId :
                itemIds) {
            Item item = itemMapper.selectItemById(itemId);

            ItemListVO itemListVO = new ItemListVO();

            if (item == null) {
                itemListVO.setId(itemId);
                itemListVO.setName("该商品已被删除");
                list.add(itemListVO);
                continue;
            }

            BeanUtils.copyProperties(item, itemListVO);

            String url = itemImageMapper.selectFirstImageUrlByItemId(itemId);
            itemListVO.setImage(url);

            List<Campus> campuses = campusMapper.selectCampusByItemId(itemId);
            itemListVO.setCampuses(campuses);

            list.add(itemListVO);
        }

        return list;
    }

    @Override
    public boolean addFollow(Long followedId) {
        Long currentUserId = getCurrentUserId();
        return followMapper.addFollow(currentUserId, followedId);
    }

    @Override
    public Long selectFollowIdByIds(Long followedId) {
        Long currentUserId = getCurrentUserId();
        return followMapper.selectIdByIds(currentUserId, followedId);
    }

    @Override
    public boolean deleteFollow(Long followedId) {
        Long currentUserId = getCurrentUserId();
        return followMapper.deleteFollow(currentUserId, followedId);
    }

    @Override
    public List<UserProfileVO> getFollowList() {
        Long currentUserId = getCurrentUserId();

        List<UserProfileVO> list = followMapper.selectFollowedUserProfileByUserId(currentUserId);

        return list;
    }

    @Override
    public Long selectViewHistoryIdByIds(Long userId, Long itemId) {
        return viewHistoryMapper.selectIdByIds(userId, itemId);
    }

    @Override
    public boolean deleteViewHistory(Long itemId) {
        Long currentUserId = getCurrentUserId();
        return viewHistoryMapper.deleteViewHistory(currentUserId, itemId);
    }

    @Override
    public PageVO getViewHistory(int page) {
        Long currentUserId = getCurrentUserId();

        PageHelper.startPage(page, 10);
        Page<ItemListVO> data = viewHistoryMapper.selectViewHistoryByUserId(currentUserId);

        long total = data.getTotal();
        List<ItemListVO> list = data.getResult();

        for (int i = 0; i < list.size(); i++) {
            ItemListVO itemListVO = list.get(i);

            Long itemId = itemListVO.getId();
            List<Campus> campuses = campusMapper.selectCampusByItemId(itemId);

            itemListVO.setCampuses(campuses);
        }

        return new PageVO(total, list);
    }
}
